import { MciSvgIcon } from '@/components/base';
import { NODE_LIST, NODE_TYPE } from '@/constants/config';
import { createGraphNode, createPortNameWithNodeType } from '@/utils/graph';
import { Graph, Node, StringExt } from '@antv/x6';
import { ElPopover } from 'element-plus';
import { BaseNodeContent } from '../..';
import { baseNodeProps } from '../../define';

export const NodeOfCreateBtn = defineComponent({
  props: {
    ...baseNodeProps
  },
  setup(props) {
    const getNextNodePosition = (node: Node, graph: Graph, dx = 300, dy = 100) => {
      // 找出画布中以该起始节点为起点的相关边的终点id集合
      const downstreamNodeIdList: string[] = [];
      graph.getEdges().forEach((edge) => {
        const originEdge = edge.toJSON()?.data;
        if (originEdge?.source === node.id) {
          downstreamNodeIdList.push(originEdge.target);
        }
      });
      // 获取起点的位置信息
      const position = node.getPosition();
      let minX = Infinity;
      let maxY = -Infinity;
      graph.getNodes().forEach((graphNode) => {
        if (downstreamNodeIdList.indexOf(graphNode.id) > -1) {
          const nodePosition = graphNode.getPosition();
          // 找到所有节点中最左侧的节点的x坐标
          if (nodePosition.x < minX) {
            minX = nodePosition.x;
          }
          // 找到所有节点中最x下方的节点的y坐标
          if (nodePosition.y > maxY) {
            maxY = nodePosition.y;
          }
        }
      });

      return {
        x: minX !== Infinity ? minX : position.x + dx,
        y: maxY !== -Infinity ? maxY + dy : position.y
      };
    };

    const createNode = (type: keyof typeof NODE_TYPE, graph: Graph, position?: { x: number; y: number }) => {
      const node = createGraphNode(graph, type, {
        nodeType: type,
        ...NODE_LIST[type]
      });
      if (position) {
        node.setPosition(position.x, position.y);
      }

      const newNode = graph.addNode(node);
      return newNode;
    };

    const createNextNode = (nodeType: keyof typeof NODE_TYPE) => {
      const { node } = props;
      const graph = node.model?.graph;
      if (graph) {
        // 获取下游节点的初始位置信息
        const position = getNextNodePosition(node, graph);
        // 创建下游节点
        const newNode = createNode(nodeType, graph, position);
        const source = node.id;
        const target = newNode.id;
        const data = node.getData();
        // 创建该节点出发到下游节点的边
        const edge = {
          id: StringExt.uuid(),
          shape: 'base-edge',
          source: {
            cell: source,
            port: createPortNameWithNodeType(data.nodeType, 'right')
          },
          target: {
            cell: target,
            port: createPortNameWithNodeType(nodeType, 'left')
          },
          zIndex: -1,
          data: {
            source,
            target
          }
        };
        if (graph) {
          graph.addEdge(edge);
        }
      }
    };

    const nodeConfig = computed(() => {
      if (!props.nodeType) return null;
      return NODE_LIST[props.nodeType];
    });

    return () => {
      return (
        <ElPopover popperClass="popover-node-list" trigger="click">
          {{
            reference() {
              if (!nodeConfig.value?.nextNodeList?.length) return <div></div>;
              return (
                <div onClick={e => e.stopPropagation()} class="add-node cursor-pointer absolute top-8 right-8">
                  <div class="add-node-btn">
                    <MciSvgIcon width={12} height={12} color="var(--color-grey-6)" name="plus" class="mr-8" />
                  </div>
                </div>
              );
            },
            default() {
              return (
                <div class="flex flex-col gap-2 node-list">
                  {nodeConfig.value?.nextNodeList?.map((nodeType: keyof typeof NODE_TYPE) => (
                    <BaseNodeContent
                      onClick={() => createNextNode(nodeType)}
                      nodeName={NODE_LIST[nodeType].nodeName}
                      icon={NODE_LIST[nodeType].icon}
                    />
                  ))}
                </div>
              );
            }
          }}
        </ElPopover>
      );
    };
  }
});
